﻿Imports System.ServiceModel
Imports System.ServiceModel.Description
Imports System.Activities
Imports System.Activities.Presentation
Imports System.Activities.Tracking
Imports System.Activities.Debugger

<ServiceBehavior(InstanceContextMode:=InstanceContextMode.Single)>
Public Class TraceReceiver
    Implements ITraceService, IDisposable

    Public Const NAMEDPIPE_ADDRESS As String = "net.pipe://localhost/TraceSendServices.svc"
    Public Const NAMEDPIPE_NAMESPACE As String = "http://schemas.wfdesignerexpress.jp/TraceSendService"
    Public Const VISUALTRACE_WAITTIME As Integer = 500

    Public Event TrackingRecordReceived(ByVal traceStrings As String)

    Private _service As ServiceHost = Nothing
    Public Property SrcDict As New Dictionary(Of Object, SourceLocation)
    Public Property ActivityIdDict As New Dictionary(Of String, Activity)

    ''' <summary>アプリ間通信用名前付きパイプの作成</summary>
    Public Sub OpenService()

        Dim localServiceAddress As Uri() = {New Uri(NAMEDPIPE_ADDRESS)}
        Dim svType As Type = GetType(TraceReceiver)
        _service = New ServiceHost(Me, localServiceAddress)

        Dim pipeBinding As New NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
        pipeBinding.Namespace = NAMEDPIPE_NAMESPACE

        Dim serviceMetadata As New ServiceMetadataBehavior
        _service.AddServiceEndpoint(GetType(ITraceService), pipeBinding, String.Empty)
        _service.Description.Behaviors.Add(serviceMetadata)
        _service.Open()

    End Sub

    ''' <summary>アプリ間通信用名前付きパイプの解放</summary>
    Public Sub CloseService()
        If (_service IsNot Nothing) AndAlso
                   (_service.State = CommunicationState.Opened) Then _service.Close()
    End Sub

    ''' <summary>通信サービスの処理実態</summary>
    Public Sub SendTraceData(ByVal traceData As String) Implements ITraceService.SendTraceData
        RaiseEvent TrackingRecordReceived(traceData)
    End Sub

#Region "トレース"
    Public Function CreateTrackingProfile() As TrackingProfile
        Dim trcProfile As New TrackingProfile With {.Name = "CustomTrackingProfile"}
        Dim ctQuery As New CustomTrackingQuery With {.Name = "*", .ActivityName = "*"}
        trcProfile.Queries.Add(ctQuery)

        Dim wfiQuery As New WorkflowInstanceQuery
        wfiQuery.States.Add(WorkflowInstanceStates.Started)
        wfiQuery.States.Add(WorkflowInstanceStates.Aborted)
        wfiQuery.States.Add(WorkflowInstanceStates.Canceled)
        wfiQuery.States.Add(WorkflowInstanceStates.Completed)
        wfiQuery.States.Add(WorkflowInstanceStates.Idle)
        wfiQuery.States.Add(WorkflowInstanceStates.Persisted)
        wfiQuery.States.Add(WorkflowInstanceStates.Resumed)
        wfiQuery.States.Add(WorkflowInstanceStates.Suspended)
        wfiQuery.States.Add(WorkflowInstanceStates.Terminated)
        wfiQuery.States.Add(WorkflowInstanceStates.UnhandledException)
        wfiQuery.States.Add(WorkflowInstanceStates.Unloaded)
        wfiQuery.States.Add(WorkflowInstanceStates.Unsuspended)

        Dim actQuery As New ActivityStateQuery
        actQuery.States.Add(ActivityStates.Closed)
        actQuery.Variables.Add("*")
        actQuery.Arguments.Add("*")

        trcProfile.Queries.Add(wfiQuery)

        Dim asQuery As New ActivityStateQuery With {.ActivityName = "*"}
        asQuery.States.Add("*")
        asQuery.Variables.Add("*")
        trcProfile.Queries.Add(asQuery)

        Return trcProfile
    End Function

    Public Function GetIdActivityMap() As Dictionary(Of String, Activity)
        Dim idToActivity As New Dictionary(Of String, Activity)
        For Each child In Me.SrcDict.Keys
            idToActivity.Add(child.Id, child)
        Next
        Return idToActivity
    End Function
#End Region

#Region "IDisposable Support"
    Private disposedValue As Boolean ' 重複する呼び出しを検出するには

    ' IDisposable
    Protected Overridable Sub Dispose(disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                '  マネージ状態を破棄します (マネージ オブジェクト)。
                Me.CloseService()
            End If

            '  アンマネージ リソース (アンマネージ オブジェクト) を解放し、下の Finalize() をオーバーライドします。
            '  大きなフィールドを null に設定します。
        End If
        Me.disposedValue = True
    End Sub

    '  上の Dispose(ByVal disposing As Boolean) にアンマネージ リソースを解放するコードがある場合にのみ、Finalize() をオーバーライドします。
    'Protected Overrides Sub Finalize()
    '    ' このコードを変更しないでください。クリーンアップ コードを上の Dispose(ByVal disposing As Boolean) に記述します。
    '    Dispose(False)
    '    MyBase.Finalize()
    'End Sub

    ' このコードは、破棄可能なパターンを正しく実装できるように Visual Basic によって追加されました。
    Public Sub Dispose() Implements IDisposable.Dispose
        ' このコードを変更しないでください。クリーンアップ コードを上の Dispose(ByVal disposing As Boolean) に記述します。
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

End Class
